package cn.virens.web.common;

import java.util.function.Function;
import java.util.function.Supplier;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.context.support.ApplicationObjectSupport;

import cn.hutool.core.util.StrUtil;

/**
 * 通用控制器
 * 
 * @author virens
 */
public class BaseController extends ApplicationObjectSupport {
	protected final Logger logger = LoggerFactory.getLogger(getClass());
	protected String _baseTemplateUrl = "";

	protected BaseController() {
	}

	/**
	 * @param baseTemplateUrl 模板根路径
	 */
	protected BaseController(String baseTemplateUrl) {
		if (!baseTemplateUrl.endsWith("/")) {
			this._baseTemplateUrl = baseTemplateUrl + "/";
		} else {
			this._baseTemplateUrl = baseTemplateUrl;
		}
	}

	/**
	 * 返回模板地址
	 * 
	 * @param  url 模板路径
	 * @return     模板地址
	 */
	protected final String returnUrl(String url) {
		if (StrUtil.isEmpty(url)) {
			return _baseTemplateUrl + "index";
		} else {
			return _baseTemplateUrl + url;
		}
	}

	/**
	 * 页面重定向
	 * 
	 * @param  url 重定向地址
	 * @return     重定向地址
	 */
	protected final String redirectUrl(String url) {
		if (url.lastIndexOf(".jspx") != -1) {
			return "redirect:" + url;
		} else {
			return "redirect:" + url + ".jspx";
		}
	}

	/**
	 * 请求转发
	 * 
	 * @param  url 转发地址
	 * @return     转发地址
	 */
	protected final String forwardUrl(String url) {
		return "forward:" + url;
	}

	/**
	 * 获取Session
	 * 
	 * @param  request HttpServletRequest实例
	 * @return         HttpSession
	 */
	protected final HttpSession getSession(HttpServletRequest request) {
		return getSession(request, true);
	}

	/**
	 * 获取Session
	 * 
	 * @param  request HttpServletRequest实例
	 * @param  create  是否自动创建session
	 * @return         HttpSession
	 */
	protected final HttpSession getSession(HttpServletRequest request, boolean create) {
		return request.getSession(create);
	}

	/**
	 * 使用Session
	 * 
	 * @param  <R>      返回值类型
	 * @param  request  HttpServletRequest实例
	 * @param  function 回调函数
	 * @return          Object
	 */
	protected final <R> R useSession(HttpServletRequest request, Function<HttpSession, R> function) {
		return function.apply(getSession(request));
	}

	/**
	 * 获取session值
	 * 
	 * @param  request HttpServletRequest实例
	 * @param  name    session名称
	 * @return         Object
	 */
	protected final Object getAttribute(HttpServletRequest request, String name) {
		HttpSession session = getSession(request, false);
		if (session != null) {
			return session.getAttribute(name);
		} else {
			return null;
		}
	}

	/**
	 * 获取session值
	 * 
	 * @param  <T>     返回类型
	 * @param  request HttpServletRequest实例
	 * @param  name    session名称
	 * @param  clazz   session值类型
	 * @return         Object
	 */
	protected final <T> T getAttribute(HttpServletRequest request, String name, Class<T> clazz) {
		return getAttribute(getSession(request, false), name, clazz);
	}

	/**
	 * 获取session值
	 * 
	 * @param  <T>     返回类型
	 * @param  session Session管理器
	 * @param  name    session名称
	 * @param  clazz   session值类型
	 * @return         Object
	 */
	@SuppressWarnings("unchecked")
	protected final <T> T getAttribute(HttpSession session, String name, Class<T> clazz) {
		if (session == null) { return null; }

		Object obj = session.getAttribute(name);
		if (obj == null) { return null; }

		if (clazz == String.class) {
			return (T) String.valueOf(obj);
		} else if (clazz.isAssignableFrom(obj.getClass())) {
			return (T) obj;
		} else {
			return null;
		}
	}

	/**
	 * 获取session值，如果不存在则从callable加载，并存入session
	 * 
	 * @param  <T>      返回类型
	 * @param  request  HttpServletRequest实例
	 * @param  name     session键
	 * @param  clazz    session键类型
	 * @param  supplier 不存在加载
	 * @return          Object
	 */
	protected final <T> T getAttribute(HttpServletRequest request, String name, Class<T> clazz, Supplier<T> supplier) {
		return useSession(request, (session) -> {
			if (session == null) { return null; }

			// 获取session值
			T obj = getAttribute(session, name, clazz);

			// 如果session值为空，则从supplier中加载
			if (obj == null) {
				obj = supplier.get();

				// 如果加载的session值不为空，存入session中
				if (obj != null) {
					session.setAttribute(name, obj);
				}
			}

			return obj;
		});
	}

	/**
	 * 存入session值
	 * 
	 * @param  <T>     返回类型
	 * @param  request HttpServletRequest实例
	 * @param  name    session键
	 * @param  value   session值
	 * @return         Object
	 */
	protected final <T> T setAttribute(HttpServletRequest request, String name, T value) {
		HttpSession session = getSession(request);
		if (session != null && value == null) {
			session.removeAttribute(name);
		} else if (session != null && value != null) {
			session.setAttribute(name, value);
		} else {
			return null;
		}

		return value;
	}
}
